﻿using UnityEngine;

namespace HotPlayer.Physic2D
{
    public static class GPTGJK
    {
        public static bool DetectCollision(Polygon2D shape1, Polygon2D shape2)
        {
            var direction = new Vector2(1, 0);
            var support = GJKUtils.Support(shape1, shape2, direction);
            var simplex = GJKUtils.cleanSimplex;
            simplex.Add(support);
            direction = -support;

            var loopHunter = 0;
            while (loopHunter++ < 1024)
            {
                support = GJKUtils.Support(shape1, shape2, direction);
                if (Vector2.Dot(support, direction) <= 0)
                {
                    return false; // No collision
                }

                simplex.Add(support);
                if (HandleSimplex(simplex, ref direction))
                {
                    return true; // Collision detected
                }
            }

            return false;
        }

        private static bool HandleSimplex(Simplex simplex, ref Vector2 direction)
        {
            if (simplex.Count == 3)
            {
                var a = simplex[2];
                var b = simplex[1];
                var c = simplex[0];

                var ab = b - a;
                var ac = c - a;
                var ao = -a;

                var abPerp = MathUtils.TripleProduct(ac, ab, ab);
                var acPerp = MathUtils.TripleProduct(ab, ac, ac);

                if (Vector2.Dot(abPerp, ao) > 0)
                {
                    simplex.RemoveAt(0); // Remove C
                    direction = abPerp;
                }
                else if (Vector2.Dot(acPerp, ao) > 0)
                {
                    simplex.RemoveAt(1); // Remove B
                    direction = acPerp;
                }
                else
                {
                    return true; // Collision detected
                }
            }
            else
            {
                Vector2 a = simplex[1];
                Vector2 b = simplex[0];
                Vector2 ab = b - a;
                Vector2 ao = -a;

                direction = MathUtils.TripleProduct(ab, ao, ab);
                if (Vector2.Dot(direction, direction) == 0)
                {
                    direction = Vector2.Perpendicular(ab);
                }
            }

            return false;
        }
    }
}